package com.alibaba.citrus.cr.mn.order.center.facade.function.impl;

import com.alibaba.citrus.cr.common.constant.OrderFeaturesKey;
import com.alibaba.citrus.cr.common.enums.ordercenter.InnerMessageEventEnum;
import com.alibaba.citrus.cr.common.enums.ordercenter.OrderCategoryEnum;
import com.alibaba.citrus.cr.common.enums.ordercenter.SalesOrderTypeEnum;
import com.alibaba.citrus.cr.common.exception.FunctionException;
import com.alibaba.citrus.cr.common.util.ThreadPoolUtil;
import com.alibaba.citrus.cr.mn.order.center.common.SetOrderTag;
import com.alibaba.citrus.cr.mn.order.center.common.util.StopWatchUtils;
import com.alibaba.citrus.cr.mn.order.center.facade.adapter.dataobject.response.FulfillmentDetailGetResDTO;
import com.alibaba.citrus.cr.mn.order.center.facade.function.common.AbstractOrderAtomCloseService;
import com.alibaba.citrus.cr.mn.order.center.facade.function.common.SendMsgService;
import com.alibaba.cz.base.tool.log.Log;
import com.alibaba.fastjson.JSON;
import com.epoch.app.crb2btradecenter.sdo.OrderLineSDO;
import com.epoch.app.crb2btradecenter.sdo.OrderSDO;
import com.epoch.app.mnordercenter.model.dto.OrderAtomBatchCloseRequest;
import com.epoch.app.mnordercenter.orderbaserequest.OrderAtomCloseRequest;
import com.epoch.app.mnordercenter.orderbaserequest.OrderAtomCloseResponse;
import com.google.common.collect.Lists;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.CountDownLatch;
import java.util.stream.Collectors;

/**
 * @auther dongju.fyj
 * @date 2023/4/21
 */
@Service("salesOrderAtomSyncCloseService")
public class SalesOrderAtomSyncCloseServiceImpl extends AbstractOrderAtomCloseService {

    private static final Log log = Log.getLogger(SalesOrderAtomSyncCloseServiceImpl.class);

    @Resource
    private SendMsgService sendMsgService;

    @Override
    public String getOrderTagNameForErrorMsg() {
        return "OC-01-001-01-16-016";
    }

    @Override
    protected String getOrderTag() {
        return SetOrderTag.NORMAL;
    }

    @Override
    public List<OrderAtomCloseResponse> batchClose(OrderAtomBatchCloseRequest request) {
        // 入参校验
        StopWatchUtils.start("订单同步批量关闭", "paramsCheck");
        super.paramsCheck(request, request.getOrderCategoryCode());
        StopWatchUtils.stop();

        // 查询销售订单数据
        StopWatchUtils.start("订单同步批量关闭", "querySalesOrder");
        List<OrderSDO> orderSDOS = querySalesOrder(request);
        StopWatchUtils.stop();

        // 构造返回结果
        List<OrderAtomCloseResponse> closeResponses = new ArrayList<>();

        // 查询履约单数据
        StopWatchUtils.start("订单同步批量关闭", "searchFulfillmentOrderList");
        List<FulfillmentDetailGetResDTO> fulfillmentDetailDTOList = this.searchFulfillmentOrderList(orderSDOS, closeResponses);
        StopWatchUtils.stop();

        // 识别F-B-b订单
        boolean isStockOrder = OrderCategoryEnum.STOCK.getCode().equals(request.getOrderCategoryCode());

        // 根据订单单号缓存订单
        StopWatchUtils.start("订单同步批量关闭", "cacheOrder");
        Map<String, OrderSDO> orderMap = new HashMap<>();
        Map<String, OrderSDO> relationOrderMap = new HashMap<>();
        for (OrderSDO orderSDO : orderSDOS) {
            if (isStockOrder && SalesOrderTypeEnum.GROUP_STD_ORDER.getCode().equals(orderSDO.getOrderType())) {
                // F-B-b场景，缓存F-B订单
                relationOrderMap.put(orderSDO.getRelationNo(), orderSDO);
                continue;
            }
            orderMap.put(orderSDO.getOrderBizId(), orderSDO);
        }
        StopWatchUtils.stop();

        // 根据订单单号+订单行号缓存订单行
        Map<String, Map<String, OrderLineSDO>> orderLineMap = new HashMap<>();
        Map<String, Map<String, OrderLineSDO>> relationOrderLineMap = new HashMap<>();

        List<OrderAtomCloseRequest> orderList = Lists.newArrayList(request.getOrderList());
        Iterator<OrderAtomCloseRequest> iterator = orderList.iterator();
        StopWatchUtils.start("订单同步批量关闭", "iterator");
        while (iterator.hasNext()) {
            OrderAtomCloseRequest orderAtomCloseRequest = iterator.next();

            OrderAtomCloseResponse closeResponse = new OrderAtomCloseResponse();
            closeResponse.setSalesOrderNo(orderAtomCloseRequest.getSalesOrderNo());
            closeResponse.setLineNum(orderAtomCloseRequest.getLineNum());
            closeResponse.setSuccess(Boolean.FALSE);

            OrderSDO order = orderMap.get(orderAtomCloseRequest.getSalesOrderNo());
            log.info("SalesOrderAtomSyncCloseServiceImpl#batchClose order={}", JSON.toJSONString(order));
            if (Objects.isNull(order)) {
                throw new FunctionException("OC-01-001-01-16-016", orderAtomCloseRequest.getSalesOrderNo());
            }
            OrderSDO relationOrder = relationOrderMap.get(orderAtomCloseRequest.getSalesOrderNo());
            if (isStockOrder) {
                log.info("SalesOrderAtomSyncCloseServiceImpl#batchClose relationOrder={}", JSON.toJSONString(relationOrder));
            }

            if (!orderLineMap.containsKey(orderAtomCloseRequest.getSalesOrderNo())) {
                // 缓存订单行
                Map<String, OrderLineSDO> tempLineMap = new HashMap<>();
                for (OrderLineSDO orderLine : order.getOrderLineSDOS()) {
                    tempLineMap.put(orderLine.getSerialNumber(), orderLine);
                }
                orderLineMap.put(orderAtomCloseRequest.getSalesOrderNo(), tempLineMap);

                if (Objects.nonNull(relationOrder)) {
                    Map<String, OrderLineSDO> tempRelationLineMap = new HashMap<>();
                    for (OrderLineSDO orderLine : relationOrder.getOrderLineSDOS()) {
                        tempRelationLineMap.put(orderLine.getSerialNumber(), orderLine);
                    }
                    relationOrderLineMap.put(orderAtomCloseRequest.getSalesOrderNo(), tempRelationLineMap);
                }
            }

            // 根据订单行号取出订单行数据
            OrderLineSDO orderLine = orderLineMap.get(orderAtomCloseRequest.getSalesOrderNo()).get(orderAtomCloseRequest.getLineNum());
            // 校验订单行
            String message = this.checkOrderLine(orderLine, closeResponse);
            log.info("SalesOrderAtomSyncCloseServiceImpl#batchClose message:{}", JSON.toJSONString(message));
            if (StringUtils.isNotBlank(message)) {
                // 校验不通过，组装错误信息
                closeResponses.add(closeResponse);
                iterator.remove();
                continue;
            }
            // 校验F-B-b订单里的F-B订单行
            if (isStockOrder && relationOrderLineMap.containsKey(orderAtomCloseRequest.getSalesOrderNo())) {
                // 根据订单行号取出订单行数据
                OrderLineSDO relationOrderLine = relationOrderLineMap.get(orderAtomCloseRequest.getSalesOrderNo()).get(orderAtomCloseRequest.getLineNum());
                message = this.checkOrderLine(relationOrderLine, closeResponse);
                log.info("SalesOrderAtomSyncCloseServiceImpl#batchClose message:{}", JSON.toJSONString(message));
                if (StringUtils.isNotBlank(message)) {
                    // 校验不通过，组装错误信息
                    closeResponses.add(closeResponse);
                    iterator.remove();
                    continue;
                }
            }

            // 校验订单
            message = this.checkOrder(order, orderAtomCloseRequest.getSalesOrderNo(), closeResponse);
            log.info("SalesOrderAtomSyncCloseServiceImpl#batchClose message:{}", JSON.toJSONString(message));
            if (StringUtils.isNotBlank(message)) {
                // 校验不通过，组装错误信息
                closeResponses.add(closeResponse);
                iterator.remove();
                continue;
            }
            // 校验F-B-b订单里的F-B订单
            if (Objects.nonNull(relationOrder)) {
                message = this.checkOrder(relationOrder, orderAtomCloseRequest.getSalesOrderNo(), closeResponse);
                log.info("SalesOrderAtomSyncCloseServiceImpl#batchClose message:{}", JSON.toJSONString(message));
                if (StringUtils.isNotBlank(message)) {
                    // 校验不通过，组装错误信息
                    closeResponses.add(closeResponse);
                    iterator.remove();
                    continue;
                }
            }

            // 校验履约单
            boolean status = this.checkFulfillmentOrder(order, orderLine, fulfillmentDetailDTOList, closeResponses);
            log.info("SalesOrderAtomSyncCloseServiceImpl#batchClose status:{}", JSON.toJSONString(status));
            if (!status) {
                // 校验不通过
                iterator.remove();
                continue;
            }
        }
        StopWatchUtils.stop();

        if (CollectionUtils.isEmpty(orderList)) {
            return closeResponses;
        }

        // 保存要调用sap拒绝接口的数据
        List<OrderAtomCloseRequest> sapCloseRequests = new ArrayList<>();
        // 校验订单、补充外部单号和外部行号
        StopWatchUtils.start("订单同步批量关闭", "sapCloseRequests");
        for (OrderAtomCloseRequest orderAtomCloseRequest : orderList) {
            try {
                OrderSDO order = orderMap.get(orderAtomCloseRequest.getSalesOrderNo());
                OrderLineSDO orderLine = orderLineMap.get(orderAtomCloseRequest.getSalesOrderNo()).get(orderAtomCloseRequest.getLineNum());
                if (StringUtils.isBlank(order.getOuterOrderId()) || StringUtils.isBlank(orderLine.getOuterOrderLineId())) {
                    log.info("SalesOrderAtomSyncCloseServiceImpl#batchClose {}/{} outKey is empty", order.getOrderBizId(), orderLine.getSerialNumber());
                    continue;
                }
                // 设置外部单号和行号，调用sap拒绝接口时使用
                orderAtomCloseRequest.setOutOrderNo(order.getOuterOrderId());
                orderAtomCloseRequest.setOutLineNum(orderLine.getOuterOrderLineId());
                sapCloseRequests.add(orderAtomCloseRequest);

                if (isStockOrder) {
                    order = relationOrderMap.get(orderAtomCloseRequest.getSalesOrderNo());
                    orderLine = relationOrderLineMap.get(orderAtomCloseRequest.getSalesOrderNo()).get(orderAtomCloseRequest.getLineNum());
                    if (StringUtils.isBlank(order.getOuterOrderId()) || StringUtils.isBlank(orderLine.getOuterOrderLineId())) {
                        log.info("SalesOrderAtomSyncCloseServiceImpl#batchClose {}/{} outKey is empty", order.getOrderBizId(), orderLine.getSerialNumber());
                        continue;
                    }
                    OrderAtomCloseRequest relationOrderAtomCloseRequest = new OrderAtomCloseRequest();
                    BeanUtils.copyProperties(orderAtomCloseRequest, relationOrderAtomCloseRequest);
                    // 设置外部单号和行号，调用sap拒绝接口时使用
                    relationOrderAtomCloseRequest.setOutOrderNo(order.getOuterOrderId());
                    relationOrderAtomCloseRequest.setOutLineNum(orderLine.getOuterOrderLineId());
                    relationOrderAtomCloseRequest.setSalesOrderNo(order.getOrderBizId());
                    sapCloseRequests.add(relationOrderAtomCloseRequest);
                }
            } catch (Exception e) {
                log.error("SalesOrderAtomSyncCloseServiceImpl#batchClose sapCloseRequests error", e);
            }
        }
        StopWatchUtils.stop();

        Map<String, List<OrderAtomCloseRequest>> orderAtomCloseMap = orderList.stream().collect(Collectors.groupingBy(OrderAtomCloseRequest::getSalesOrderNo));
        List<OrderSDO> ordersToReleaseOccpuy = Collections.synchronizedList(new ArrayList<>());
        // List<String> salesOrderNos = Collections.synchronizedList(new ArrayList<>());
        Map<String, List<String>> salesOrderNosMap = Collections.synchronizedMap(new HashMap<>());

        StopWatchUtils.start("订单同步批量关闭", "updateOrderLineStatus");
        Date now = new Date();
        // 取出占用了活动的预报订单明细ID，用于释放活动预占
        Map<String, List<String>> forecastOrderLineIdsMap = new HashMap<>();
        CountDownLatch countDownLatch = new CountDownLatch(orderAtomCloseMap.size());
        orderAtomCloseMap.forEach((key, value) -> ThreadPoolUtil.execute(() -> {
            try {
                OrderSDO order = orderMap.get(key);
                if (Objects.isNull(order)) {
                    return;
                }
                List<OrderLineSDO> orderLineSDOS = order.getOrderLineSDOS();
                if (CollectionUtils.isEmpty(orderLineSDOS)) {
                    return;
                }
                String sequenceNo = "";
                if (Objects.nonNull(order.getFeatures()) && order.getFeatures().containsKey(OrderFeaturesKey.ACTIVITY_SEQUENCE_NO)) {
                    sequenceNo = order.getFeatures().get(OrderFeaturesKey.ACTIVITY_SEQUENCE_NO);
                    if (!forecastOrderLineIdsMap.containsKey(sequenceNo)) {
                        forecastOrderLineIdsMap.put(sequenceNo, Lists.newArrayList());
                    }
                }

                Map<String, List<OrderAtomCloseRequest>> orderAtomCloseRequestMap = value.stream().collect(Collectors.groupingBy(OrderAtomCloseRequest::getLineNum));
                List<OrderLineSDO> updateOrderLineList = new ArrayList<>();
                for (OrderLineSDO orderLine : orderLineSDOS) {
                    List<OrderAtomCloseRequest> orderAtomCloseRequestList = orderAtomCloseRequestMap.get(orderLine.getSerialNumber());
                    if (CollectionUtils.isEmpty(orderAtomCloseRequestList)) {
                        // 当前行未进行拒绝操作，直接跳过
                        continue;
                    }
                    OrderAtomCloseRequest orderAtomCloseRequest = orderAtomCloseRequestList.get(0);
                    orderLine.setRefuseReasonCode(orderAtomCloseRequest.getCloseCode());
                    order.setModifierId(orderAtomCloseRequest.getModifierCode());
                    order.setModifierName(orderAtomCloseRequest.getModifierName());
                    updateOrderLineList.add(orderLine);
                }

                // 更新订单明细状态
                boolean updateOrderLineStatusSuccess = super.updateOrderLineStatus(order, updateOrderLineList);
                if (updateOrderLineStatusSuccess) {
                    for (OrderLineSDO orderLine : updateOrderLineList) {
                        OrderAtomCloseResponse closeResponse = new OrderAtomCloseResponse();
                        closeResponse.setSalesOrderNo(order.getOrderBizId());
                        closeResponse.setLineNum(orderLine.getSerialNumber());
                        closeResponse.setSuccess(true);
                        closeResponses.add(closeResponse);

                        // 取出预报订单明细ID，用于释放活动预占
                        if (StringUtils.isNotBlank(sequenceNo) && Objects.nonNull(orderLine.getFeatures())) {
                            String forecastOrderLineId = orderLine.getFeatures().get(OrderFeaturesKey.FORECAST_ORDER_LINE_ID);
                            if (StringUtils.isNotBlank(forecastOrderLineId)) {
                                List<String> forecastOrderLineIds = forecastOrderLineIdsMap.get(sequenceNo);
                                forecastOrderLineIds.add(forecastOrderLineId);
                                forecastOrderLineIdsMap.put(sequenceNo, forecastOrderLineIds);
                            }
                        }
                    }
                } else {
                    for (OrderLineSDO orderLine : updateOrderLineList) {
                        OrderAtomCloseResponse closeResponse = new OrderAtomCloseResponse();
                        closeResponse.setSalesOrderNo(order.getOrderBizId());
                        closeResponse.setLineNum(orderLine.getSerialNumber());
                        closeResponse.setErrorCode("OC-01-004-01-16-006");
                        closeResponse.setMessage("关闭销售订单行失败");
                        closeResponse.setSuccess(false);
                        closeResponses.add(closeResponse);
                    }
                    return;
                }

                // 根据所有订单行状态判断是否需要将订单设为已取消
                OrderAtomCloseRequest orderAtomCloseRequest = orderList.get(0);
                order.setModifierId(orderAtomCloseRequest.getModifierCode());
                order.setModifierCode(orderAtomCloseRequest.getModifierCode());
                order.setModifierName2(orderAtomCloseRequest.getModifierName());
                order.setGmtModified(now);
                this.updateOrderStatus(order, order.getOrderLineSDOS());

                // 更新F-B-b场景里的F-B订单数据
                if (isStockOrder) {
                    OrderSDO relationOrder = relationOrderMap.get(key);
                    if (Objects.nonNull(relationOrder)) {
                        List<OrderLineSDO> relationOrderLineSDOS = relationOrder.getOrderLineSDOS();

                        List<OrderLineSDO> updateRelationOrderLineList = new ArrayList<>();
                        for (OrderLineSDO relationOrderLine : relationOrderLineSDOS) {
                            List<OrderAtomCloseRequest> orderAtomCloseRequestList = orderAtomCloseRequestMap.get(relationOrderLine.getSerialNumber());
                            if (CollectionUtils.isEmpty(orderAtomCloseRequestList)) {
                                // 当前行未进行拒绝操作，直接跳过
                                continue;
                            }
                            orderAtomCloseRequest = orderAtomCloseRequestList.get(0);
                            relationOrderLine.setRefuseReasonCode(orderAtomCloseRequest.getCloseCode());
                            relationOrder.setModifierId(orderAtomCloseRequest.getModifierCode());
                            relationOrder.setModifierName(orderAtomCloseRequest.getModifierName());
                            updateRelationOrderLineList.add(relationOrderLine);
                        }
                        this.updateOrderLineStatus(relationOrder, updateRelationOrderLineList);

                        // 根据所有订单行状态判断是否需要将订单设为已取消
                        orderAtomCloseRequest = orderList.get(0);
                        relationOrder.setModifierId(orderAtomCloseRequest.getModifierCode());
                        relationOrder.setModifierCode(orderAtomCloseRequest.getModifierCode());
                        relationOrder.setModifierName2(orderAtomCloseRequest.getModifierName());
                        relationOrder.setGmtModified(now);
                        this.updateOrderStatus(relationOrder, relationOrder.getOrderLineSDOS());
                    }
                }

                // 记录需要释放库存的订单
                ordersToReleaseOccpuy.add(order);

                // 记录关闭成功的销售订单号
                // salesOrderNos.add(order.getOrderBizId());
                salesOrderNosMap.put(order.getOrderBizId(), updateOrderLineList.stream().map(OrderLineSDO::getSerialNumber).collect(Collectors.toList()));
            } catch (Exception e) {
                log.error("SalesOrderAtomSyncCloseServiceImpl#batchClose updateOrderStatus error", e);
            } finally {
                countDownLatch.countDown();
            }
        }));

        try {
            countDownLatch.await();
        } catch (Exception e) {
            log.error("SalesOrderAtomSyncCloseServiceImpl#batchClose await error", e);
        }
        StopWatchUtils.stop();

        // 2.分公司订单释放库存预占
        if (OrderCategoryEnum.COMPANY.getCode().equals(request.getOrderCategoryCode())) {
            StopWatchUtils.start("订单同步批量关闭", "sendMsgToInventoryRelease");
            sendMsgService.sendMsgToInventoryRelease(ordersToReleaseOccpuy);
            StopWatchUtils.stop();
        }

        // 3.发送MQ消息通知其他中心
        StopWatchUtils.start("订单同步批量关闭", "sendSalesOrderChangeMsg");
        sendMsgService.sendSalesOrderChangeMsg(salesOrderNosMap, InnerMessageEventEnum.SALES_ORDER_REFUSED);
        StopWatchUtils.stop();

        // 4.发送消息触发调用sap拒绝接口
        StopWatchUtils.start("订单同步批量关闭", "sendMessage");
        log.info("SalesOrderAtomSyncCloseServiceImpl#batchClose sapCloseRequests={}", JSON.toJSONString(sapCloseRequests));
        if (CollectionUtils.isNotEmpty(sapCloseRequests)) {
            sendMsgService.sendSalesOrderRefuseMsg(JSON.toJSONString(sapCloseRequests));
        }
        StopWatchUtils.stop();

        // 5.发送消息释放活动预占
        StopWatchUtils.start("订单同步批量关闭", "sendMessage");
        try {
            log.info("SalesOrderAtomSyncCloseServiceImpl#batchClose forecastOrderLineIdsMap={}", JSON.toJSONString(forecastOrderLineIdsMap));
            forecastOrderLineIdsMap.forEach((sequenceNo, forecastOrderLineIds) -> {
                if (StringUtils.isBlank(sequenceNo) || CollectionUtils.isEmpty(forecastOrderLineIds)) {
                    return;
                }
                sendMsgService.sendActivityFailMsg(sequenceNo, forecastOrderLineIds.stream().map(Long::valueOf).collect(Collectors.toList()));
            });
        } catch (Exception e) {
            log.error("SalesOrderAtomSyncCloseServiceImpl#batchClose sendActivityFailMsg error", e);
        }
        StopWatchUtils.stop();

        return closeResponses;
    }
}
